/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package service.reportCenter.packageSalesReport;

import com.openbrew.openbrewrf.Customer;
import com.openbrew.openbrewrf.CustomerGroup;
import com.openbrew.openbrewrf.FinishedGoodsInventory;
import com.openbrew.openbrewrf.LegacySales;
import com.openbrew.openbrewrf.Sales;
import com.openbrew.openbrewrf.views.PackageTypeView;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

/**
 *
 * @author chapmand
 */
@Stateless
@Path("com.openbrew.openbrewrf.ptreport")
public class PTReportREST {

    @PersistenceContext(unitName = "com.openBrew_openBrewRF_war_1.0PU")
    private EntityManager em;

    public PTReportREST() {
    }
    
    private final String CSVHDR = "Year/Month,Beer Name,Package Type,Qty Sold,\n";
    
    @GET
    @Path("{startDate}/{stopDate}/{custGroupID}")
    @Produces(MediaType.APPLICATION_XML)
    public List<PTReport> find(@PathParam("startDate") Date startDate
            , @PathParam("stopDate") Date stopDate, @PathParam("custGroupID") Integer custGroupID) {
        return runReport(startDate, stopDate, custGroupID);
    }
    
    @GET
    @Path("getCSV/{startDate}/{stopDate}/{custGroupID}")
    @Produces({"text/plain"})
    public Response createCSV(@PathParam("startDate") final Date startDate
            , @PathParam("stopDate") final Date stopDate, @PathParam("custGroupID") final Integer custGroupID) {
        List<PTReport> ptRep = runReport(startDate, stopDate, custGroupID);

        //Set csv info:
        String csv = "";
        if (custGroupID == 0) {
            csv += "Customer Group: All Customer Groups\n\n";
        } else {
            csv += "Customer Group: " + getCustGroup(em, custGroupID).getCustomerGroupDescription() + "\n\n";
        }
        csv += CSVHDR;
        for (final PTReport pt : ptRep) {
            csv += Integer.toString(pt.getMonth() + 1) + "/" + Integer.toString(pt.getYear())
                    + "," + pt.getBeer().getbName()
                    + "," + pt.getPackageType().getPackageTypeDesc()
                    + "," + Integer.toString(pt.getQty())
                    + ",\n";
        }
        return Response.ok(csv).header("Content-Disposition", "attachment; filename=ptReport.csv").build();
    }
    
    private List<PTReport> runReport(final Date startDate, final Date stopDate, final int custGroupID){
        List<PTReport> ptRep = new ArrayList<PTReport>();
        List<FinishedGoodsInventory> fgis = getFGIs(em);
        List<PackageTypeView> packageTypes = getPackageTypes(em);
        
        // get dates specified.
        Calendar cStart = Calendar.getInstance();      
        cStart.setTime(startDate);
        cStart.set(Calendar.HOUR_OF_DAY, 0);
        cStart.set(Calendar.MINUTE, 0);
        cStart.set(Calendar.SECOND, 0);
        cStart.set(Calendar.MILLISECOND, 0); 
        final Date start = cStart.getTime();
        cStart.set(Calendar.DAY_OF_MONTH, Calendar.getInstance().getActualMinimum(Calendar.DAY_OF_MONTH));

        Calendar cStop = Calendar.getInstance();      
        cStop.setTime(stopDate);
        cStop.set(Calendar.HOUR_OF_DAY, 24);
        cStop.set(Calendar.MINUTE, 59);
        cStop.set(Calendar.SECOND, 59);
        cStop.set(Calendar.MILLISECOND, 59); 
        final Date stop = cStop.getTime();
        cStop.set(Calendar.DAY_OF_MONTH, Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH));
        
        Calendar cTemp = Calendar.getInstance();
        
        List<Sales> sales = new ArrayList<Sales>();
        if(custGroupID == 0){
            sales = getAllSalesBetweenDates(start, stop, em);
        } else {
            sales = getAllSalesBetweenDatesPerCustomerGroup(start, stop, (int)custGroupID, em);
        }
        
        while(cStart.before(cStop) || cStart.equals(cStop)){
            for(final FinishedGoodsInventory fgi : fgis){
                for(final PackageTypeView pt : packageTypes){
                    if(fgi.getFGIPackageID().getPackageTypeID() == pt.getPackageTypeID()){
                        int qty = 0;
                        for(final Sales sale : sales){
                            cTemp.setTime(sale.getSDate());
                            if((cTemp.get(Calendar.YEAR) == cStart.get(Calendar.YEAR))
                                    && (cTemp.get(Calendar.MONTH) == cStart.get(Calendar.MONTH))){
                                if((custGroupID==0) || testCust(sale, custGroupID)){
                                    if(sale.getSalesFGIID() == null){
                                        qty += getOldCount(fgi, sale, pt);
                                    } else if(sale.getSalesFGIID().getFgiid() == fgi.getFgiid()){
                                        qty += sale.getSalesFGIQty();
                                    }
                                }
                            }
                        }
                        if(qty != 0){
                            ptRep.add(new PTReport(fgi.getFGIBeerID(), pt, cStart.get(Calendar.YEAR),cStart.get(Calendar.MONTH),qty));
                        }
                    }
                }
            }
            cStart.add(Calendar.MONTH, 1);
        }
        
        return ptRep;
    }
    
    private boolean testCust(final Sales sale, final int cg){
        boolean retVal = false;
        final Customer cust = sale.getCustID();
        if(cust != null){
            if(cust.getCustGroupID()!=null){
                if(cust.getCustGroupID().getCustomerGroupID() == cg){
                    retVal = true;
                }
            }
        }
        return retVal;
    }
    
    private int getOldCount(final FinishedGoodsInventory fgi, final Sales sale, final PackageTypeView pt){
        int retVal = 0;
        if(sale.getLegacySalesCollection()!=null){
            LegacySales ls = sale.getLegacySalesCollection().get(0);
            if(ls.getBeerID().getbId() == fgi.getFGIBeerID().getbId()){
                if(pt.getPackageTypeID() == 1){
                    retVal = ls.getNumHalf();
                } else if(pt.getPackageTypeID() == 2){
                    retVal = ls.getNumQtr();
                } else if(pt.getPackageTypeID()==3 || pt.getPackageTypeID()==4){
                    retVal = ls.getNumSix();
                } else if(pt.getPackageTypeID()==5){
                    retVal = ls.getNumTT();
                }
            }
        }
        
        return retVal;
    }
    
    /***************************************************************************
     * Database access files.
     ***************************************************************************/
    private List<Sales> getAllSalesBetweenDates(final Date startDate, final Date stopDate, final EntityManager en) {
        TypedQuery<Sales> query = en.createQuery(
            "SELECT s FROM Sales s WHERE s.sDate between ?1 AND ?2", Sales.class);
        query.setParameter(1, startDate, TemporalType.TIMESTAMP);
        query.setParameter(2, stopDate, TemporalType.TIMESTAMP);
        return query.getResultList();
    }
    
    private List<Sales> getAllSalesBetweenDatesPerCustomerGroup(final Date startDate
            , final Date stopDate, final int custGroupID, final EntityManager en) {
        TypedQuery<Sales> query = en.createQuery(
            "SELECT s FROM Sales s WHERE s.sDate between ?1 AND ?2 AND s.custID.custGroupID.customerGroupID = ?3", Sales.class);
        query.setParameter(1, startDate, TemporalType.TIMESTAMP);
        query.setParameter(2, stopDate, TemporalType.TIMESTAMP);
        query.setParameter(3, custGroupID);
        return query.getResultList();
    }
    
    private CustomerGroup getCustGroup(final EntityManager en, final int id){
        TypedQuery<CustomerGroup> query = en.createQuery(
            "SELECT c FROM CustomerGroup c WHERE c.customerGroupID = ?1", CustomerGroup.class);
        query.setParameter(1, id);
        return query.getSingleResult();
    }
    
    private List<PackageTypeView> getPackageTypes(final EntityManager en){
        TypedQuery<PackageTypeView> query = en.createQuery(
            "SELECT p FROM PackageTypeView p", PackageTypeView.class);
        return query.getResultList();
    }
    
    private List<FinishedGoodsInventory> getFGIs(final EntityManager en){
        TypedQuery<FinishedGoodsInventory> query = en.createQuery(
            "SELECT g FROM FinishedGoodsInventory g ORDER BY g.bBeerID.bName", FinishedGoodsInventory.class);
        return query.getResultList();
    }

    protected EntityManager getEntityManager() {
        return em;
    }
}
